package com.start.shop.common.weixin;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.script.DigestUtils;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.google.gson.JsonArray;
import com.start.shop.common.constant.RspCode;
import com.start.shop.common.exception.MyException;
import com.start.shop.common.util.AesCbcUtils;
import com.start.shop.common.util.HttpClientUtil;
import com.start.shop.common.util.RedisService;
import com.start.shop.common.weixin.domain.TemplateMessage;
import com.start.shop.common.weixin.domain.WxUserInfo;
import com.start.shop.common.weixin.domain.WxAccessToken;
import com.start.shop.common.weixin.domain.WxSession;


@Service
public class WxUserUtil {

    private Logger logger = LoggerFactory.getLogger(WxUserUtil.class);
    @Value("${appid}")
    private String appid;
    @Value("${secret}")
    private String secret;

    @Autowired
    RedisService redisService;

    private String httpClient(String url) {
        logger.info("【WeixinApi】【httpClient】：【url】：{}【START】", url);
        String rsqStr = "";
        try {
            URL urls = new URL(url);
            InputStream in = urls.openStream();
            InputStreamReader isr = new InputStreamReader(in);
            BufferedReader bufr = new BufferedReader(isr);
            String readStr= null;
            while ((readStr = bufr.readLine()) != null) {
            	rsqStr = rsqStr + readStr;
            }
            bufr.close();
            isr.close();
            in.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        logger.info("【WeixinApi】【httpClient】：【返回MAP】：{}【END】", rsqStr);
        return rsqStr;
    }

    /**
     * code换取用户信息
     * @param code
     * @return
     */
    public WxUserInfo code2UserInfo(String code, String encryptData, String data, String sign, String iv) {
    	WxSession wxSession = codeToSessionOpenid(code);
        logger.info("【service】【login】：授权登录");

        Map map = JSONArray.parseObject(data);
        //签名数据
        String signStr = data + wxSession.getSession_key();

        //计算签名 sha1(data+session_key)
        String sha1 = DigestUtils.sha1DigestAsHex(signStr);
        if (!sign.equals(sha1)) {
            throw new MyException(RspCode.WX_API_AUTH_FAIL);
        }

        //解密敏感用户信息
        logger.info("【service】【login】:encryptData:【{}】", encryptData);
        logger.info("【service】【login】:sessionKey:【{}】", wxSession.getSession_key());

        WxUserInfo wxUserInfo = null;
        try {
        	wxUserInfo = JSON.parseObject(AesCbcUtils.decrypt(encryptData, wxSession.getSession_key(), iv, "UTF-8"),WxUserInfo.class);
            logger.info("【service】【login】:unionId:【{}】", wxUserInfo.toString());
        } catch (Exception e) {
            throw new MyException(RspCode.WX_API_AUTH_FAIL);
        }

        wxUserInfo.setOpenId(wxSession.getOpenid());

        return wxUserInfo;
    }

    public WxSession codeToSessionOpenid(String code) {

        logger.info("【WeixinApi】【codeToSessionOpenid】：【code】：{}[START]", code);

        //组建微信js服务URL
        String url = "https://api.weixin.qq.com/sns/jscode2session?appid=" + this.appid +
                "&secret=" + secret + "&js_code=" + code + "&grant_type=authorization_code";

        //URL访问获取sessionid和openid
        String res = httpClient(url);
        logger.info(res);
        return JSON.parseObject(res, WxSession.class);
    }

    /**
     * 接口调用凭证获取
     * 获取小程序全局唯一后台接口调用凭据（access_token）
     *
     * @param url
     * @return
     */

    @Cacheable(cacheNames = "weixin::getAccessToken",key = "'access_token'")
    public String getAccessToken() {

        //组建微信js服务URL
        String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + appid +
                "&secret=" + secret;

        //URL访问获取sessionid和openid
        String res = httpClient(url);
        WxAccessToken wxAccessToken = JSON.parseObject(res, WxAccessToken.class);
        //插入redies
        return wxAccessToken.getAccess_token();
    }


    /**
     * 发送模板消息
     *
     * @param toUser:接收人openid
     * @param templateId：模板编号
     * @param formId:          发送编号
     * @param keyValue1：       信息1
     * @param keyValue2：       信息2
     * @param keyValue3：       信息3
     * @param keyValue4：       信息4
     * @return
     */
    @Async
    public void sendTemplateMessage(String toUser, String templateId, String formId, String keyValue1, String keyValue2, String keyValue3, String keyValue4) {

        logger.info("【WeixinApi】【sendTemplateMessage】：发送模板消息[START]");

        //组建微信js服务URL
        String url = "https://api.weixin.qq.com/cgi-bin/message/wxopen/template/send?access_token=" + getAccessToken();
        //6kXvpohK_oblhYMViIbjmMb3miPa3_-ig2pGabJJxaI

        logger.info("【WeixinApi】【sendTemplateMessage】：发送模板消息URL：{}[START]", url);

        TemplateMessage templateMessage = new TemplateMessage();
        templateMessage.setTouser(toUser);
        templateMessage.setForm_id(formId);
        templateMessage.setEmphasis_keyword("");
        templateMessage.setTemplate_id(templateId);


        Map keyWordMap1 = new HashMap();
        Map keyWordMap2 = new HashMap();
        Map keyWordMap3 = new HashMap();
        Map keyWordMap4 = new HashMap();

        keyWordMap1.put("value", keyValue1);
        keyWordMap2.put("value", keyValue2);
        keyWordMap3.put("value", keyValue3);
        keyWordMap4.put("value", keyValue4);

        Map data = new HashMap();
        data.put("keyword1", keyWordMap1);
        data.put("keyword2", keyWordMap2);
        data.put("keyword3", keyWordMap3);
        data.put("keyword4", keyWordMap4);

        templateMessage.setData(data);


        //JsonUtil.toJson(templateMessage);
        logger.info("【WeixinApi】【codeToSessionOpenid】：发送模板消息：{}[START]", JSONArray.toJSONString(templateMessage));

        String postData = JSONArray.toJSONString(templateMessage);
//		//URL访问获取sessionid和openid
        try {
            String res = HttpClientUtil.doPost(url, postData);
            logger.info("url返回结果：" + res);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    /**
     * 生成小程序二维码
     *
     * @param scene 参数
     * @param path  路径
     * @return 返回Base64的图片编码
     * @throws WeixinException
     */
    public String createQRCode(String scene, String path)  {
        logger.info("【WeixinApi】【createQRCode】：生成小程序二维码[START]");
        //组建微信js服务URL
        String url = "https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=" + getAccessToken();

        Map data = new HashMap();
        data.put("scene", scene);
        data.put("page", path);
        data.put("width", 280);
        data.put("is_hyaline", true);
        String postData = JSONArray.toJSONString(data);

        logger.info("【WeixinApi】url：{}  , postData :{}[START]", url, postData);
        //URL访问获取sessionid和openid
        try {
            byte[] res = HttpClientUtil.postUrl(url, postData);
            String base64 = org.apache.commons.codec.binary.Base64.encodeBase64String(res);
            //logger.info("url返回结果：{}" , base64);
            return base64;
        } catch (Exception e) {
            e.printStackTrace();
            throw new MyException(RspCode.WX_API_GET_CODE_FAIL);
        }
    }


}
